package com.mark.util.wxmp;

import com.mark.util.JsonUtil;
import com.mark.util.XMLUtil;
import com.mark.util.wxmp.mpbeans.Menu;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by macmatilda on 19/07/2017.
 */
@Component
public class WeixinMPClient {
    private static Logger logger = LoggerFactory.getLogger(WeixinMPClient.class);
    public static final String SCOPE_snsapi_userinfo = "snsapi_userinfo";
    public static final String SCOPE_snsapi_base = "snsapi_base";
    public static final String RESULT_SUCCESS = "0";
    public static final int RESULT_SUCCESS_INT = 0;
    public static final String KEY_ACCESS_TOKEN = "access_token";
    public static final String KEY_TICKET = "ticket";
    public static final String KEY_ERROR_CODE = "errcode";
    public static final String KEY_ERROR_MESSAGE = "errmsg";
    public static final String KEY_OPENID = "openid";
    public static final String KEY_UNIONID = "unionid";
    public static final String KEY_APPID = "appId";
    public static final String KEY_TIMESTAMP = "timestamp";
    public static final String KEY_SIGN_TIMESTAMP = "timeStamp";
    public static final String KEY_NONCESTR = "nonceStr";
    public static final String KEY_SIGNATURE = "signature";

    public static final String KEY_ERROR_SCOPE = "scope";

    public static Client client = ClientBuilder.newClient();

    public static Client getClient() {
        return client;
    }

    public static String getAccessToken(String appId, String appSecret) {
        try {
            Response response = getClient().target("https://api.weixin.qq.com/cgi-bin/token")
                .queryParam("grant_type", "client_credential")
                .queryParam("appid", appId)
                .queryParam("secret", appSecret)
                .request()
                .get(Response.class);
            Map result = response.readEntity(Map.class);
            logger.info(JsonUtil.bean2Json(result));
            int errorCode = !result.containsKey(KEY_ERROR_CODE) ? RESULT_SUCCESS_INT : (int) result.get(KEY_ERROR_CODE);
            if (RESULT_SUCCESS_INT == errorCode) {
                String accessToken = result.get(KEY_ACCESS_TOKEN).toString();
                return accessToken;
            } else {
                String errorMessage = result.get(KEY_ERROR_MESSAGE).toString();
                logger.error("get_accesstoken_error errorCode:" + errorCode + ", errorMessage:" + errorMessage);
                return null;
            }
        } catch (Exception e) {
            logger.error("", e);
            return null;
        }
    }

    public String getTicket(String accessToken) {
        try {
            Response response = getClient().target("https://api.weixin.qq.com/cgi-bin/ticket/getticket")
                .queryParam("access_token", accessToken)
                .queryParam("type", "jsapi")
                .request()
                .get(Response.class);
            Map result = response.readEntity(Map.class);
            logger.info(JsonUtil.bean2Json(result));
            int errorCode = !result.containsKey(KEY_ERROR_CODE) ? RESULT_SUCCESS_INT : (int) result.get(KEY_ERROR_CODE);
            if (RESULT_SUCCESS_INT == errorCode) {
                String ticket = result.get(KEY_TICKET).toString();
                return ticket;
            } else {
                String errorMessage = result.get(KEY_ERROR_MESSAGE).toString();
                logger.error("get_ticket_error errorCode:" + errorCode + ", errorMessage:" + errorMessage);
                return null;
            }
        } catch (Exception e) {
            logger.error("", e);
            return null;
        }
    }

//    https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN

    public void registerMenu(String accessToken, Menu menu) {
        try {
            Response response = getClient().target("https://api.weixin.qq.com/cgi-bin/menu/create")
                .queryParam("access_token", accessToken)
                .request()
                .post(Entity.entity(JsonUtil.bean2Json(menu), MediaType.APPLICATION_JSON_TYPE), Response.class);
            if (response.getStatus() == 200) {
                Map result = response.readEntity(Map.class);
                logger.info(JsonUtil.bean2Json(result));
                int errorCode = !result.containsKey(KEY_ERROR_CODE) ? RESULT_SUCCESS_INT : (int) result.get(KEY_ERROR_CODE);
                if (RESULT_SUCCESS_INT == errorCode) {
                    logger.error("register ok");
                } else {
                    String errorMessage = result.get(KEY_ERROR_MESSAGE).toString();
                    logger.error("errorCode:" + errorCode + ", errorMessage:" + errorMessage);
                }
            } else {
                logger.error("register error");
            }
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    /**
     * 网页授权的accessToken，不是公众号accessToken
     *
     * @param appId
     * @param appSecret
     * @param code
     * @return
     */
    public static Map getAccessTokenByCode(String appId, String appSecret, String code) {
        try {
            Response response = getClient().target("https://api.weixin.qq.com/sns/oauth2/access_token")
                .queryParam("appid", appId)
                .queryParam("secret", appSecret)
                .queryParam("code", code)
                .queryParam("grant_type", "authorization_code")
                .request().get(Response.class);
            String json = response.readEntity(String.class);
            Map result = JsonUtil.json2Bean(json, Map.class);
            logger.info(JsonUtil.bean2Json(result));
            int errorCode = !result.containsKey(KEY_ERROR_CODE) ? RESULT_SUCCESS_INT : (int) result.get(KEY_ERROR_CODE);
            if (RESULT_SUCCESS_INT == errorCode) {
                return result;
            } else {
                String errorMessage = result.get(KEY_ERROR_MESSAGE).toString();
                logger.error("errorCode:" + errorCode + ", errorMessage:" + errorMessage);
                return null;
            }
        } catch (Exception e) {
            logger.error("", e);
            Map map = new HashMap();
            map.put("ex", e.toString());
            return map;
        }
    }

    public static Map getUserInfo(String accessToken, String openId) {
        try {
            Response response = getClient().target("https://api.weixin.qq.com/sns/userinfo")
                .queryParam("access_token", accessToken)
                .queryParam("openid", openId)
                .queryParam("lang", "zh_CN")
                .request().get(Response.class);

            String json = response.readEntity(String.class);
            Map<String, String> result = JsonUtil.json2Bean(json, Map.class);
            String errorCode = result.containsKey(KEY_ERROR_CODE) ? result.get(KEY_ERROR_CODE) : RESULT_SUCCESS;
            String errorMessage = result.containsKey(KEY_ERROR_MESSAGE) ? result.get(KEY_ERROR_MESSAGE) : "";
            logger.error("errorCode=" + errorCode + ", errorMessage=" + errorMessage);
            return result;
        } catch (Exception e) {
            logger.error("", e);
            return null;
        }
    }

    public String getPayPreOrder(Map<String, Object> parameters) {
        String message = XMLUtil.map2xml(parameters);

        logger.error("message:" + message);
        try {
            Response response = getClient().target("https://api.mch.weixin.qq.com/pay/unifiedorder")
                .request().post(Entity.entity(message, MediaType.APPLICATION_XML_TYPE));

            String xml = response.readEntity(String.class);
            Map<String, String> result = XMLUtil.xml2map(xml);
            logger.error("result:" + result.toString());
            if ("SUCCESS".equals(result.get("return_code"))) {
                return result.get("prepay_id").toString();
            }
            return null;
        } catch (Exception e) {
            logger.error("", e);
            return null;
        }
    }

    //    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
//    https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
    public static boolean sendMessage(String accessToken,
                                      String openId,
                                      String templateId,
                                      String url,
                                      Map<String, Map<String, String>> data
    ) {
        logger.info("sendMessage, openId:" + openId + ", templateId:" + templateId);
        Map packageMap = new HashMap();
        packageMap.put("touser", openId);
        packageMap.put("template_id", templateId);
        if (url != null) {
            packageMap.put("url", url);
        }
        packageMap.put("data", data);
        try {
            Response response = getClient().target("https://api.weixin.qq.com/cgi-bin/message/template/send")
                .queryParam("access_token", accessToken)
                .request().post(Entity.entity(packageMap, MediaType.APPLICATION_JSON));

            String json = response.readEntity(String.class);
            Map<String, String> result = JsonUtil.json2Bean(json, Map.class);
            logger.error("result:" + result.toString());
            return true;
        } catch (Exception e) {
            logger.error("", e);
            return false;
        }
    }
}